package cn.schoolwow.workflow.module.task.action.flow.common;

import cn.schoolwow.quickdao.domain.transaction.Transaction;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.query.instanceList.QueryInstanceList;
import cn.schoolwow.workflow.domain.deploy.DeployApprovalType;
import cn.schoolwow.workflow.domain.instance.ManualWorkFlowAssigner;
import cn.schoolwow.workflow.domain.task.WorkFlowAssigner;
import cn.schoolwow.workflow.entity.WorkFlowInstance;
import cn.schoolwow.workflow.entity.WorkFlowNode;
import cn.schoolwow.workflow.entity.WorkFlowTask;
import cn.schoolwow.workflow.module.common.domain.WorkFlowTaskType;
import cn.schoolwow.workflow.module.task.action.domain.CompleteTaskOption;
import com.alibaba.fastjson.JSONArray;

import java.util.ArrayList;
import java.util.List;

public class SetWorkFlowTaskListCommonFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        WorkFlowNode workFlowNode = flowContext.checkInstanceData(WorkFlowNode.class);

        List<WorkFlowTask> workFlowTaskList = new ArrayList<>();
        flowContext.putTemporaryData("workFlowTaskList", workFlowTaskList);

        JSONArray assignerArray = workFlowNode.getAssigner();
        List<WorkFlowAssigner> workFlowAssignerList = assignerArray.toJavaList(WorkFlowAssigner.class);
        flowContext.putCurrentFlowData("workFlowAssignerList", workFlowAssignerList);

        //判断多人审批类型
        if(null==workFlowNode.getApprovalType()){
            addAllAssigner(flowContext);
        }else{
            DeployApprovalType deployApprovalType = DeployApprovalType.getDeployApprovalType(workFlowNode.getApprovalType());
            switch (deployApprovalType){
                case AllApproval:{addAllAssigner(flowContext);}break;
                case AnyApproval:{addAllAssigner(flowContext);}break;
                case SequentialApproval:{addSequentialAssigner(flowContext);}break;
            }
        }
        replaceAssignerList(flowContext);
    }

    @Override
    public String name() {
        return "设置工作流任务列表公共流程";
    }

    private void addAllAssigner(FlowContext flowContext){
        WorkFlowNode workFlowNode = flowContext.checkInstanceData(WorkFlowNode.class);
        WorkFlowInstance workFlowInstance = flowContext.checkInstanceData(WorkFlowInstance.class);
        List<WorkFlowAssigner> workFlowAssignerList = flowContext.checkData("workFlowAssignerList", List.class);
        Transaction transaction = flowContext.checkInstanceData(Transaction.class);

        //若当前节点已经存在任务,则不再插入新任务
        long count = transaction.query(WorkFlowTask.class)
                .addQuery("instanceId", workFlowInstance.getId())
                .addQuery("nodeId", workFlowNode.getId())
                .addQuery("type", WorkFlowTaskType.AuditTask.value)
                .execute()
                .count();
        if(count>0){
            return;
        }

        for(int i=0;i<workFlowAssignerList.size();i++){
            addWorkFlowTaskByWorkFlowAssigner(i, flowContext);
        }
    }

    private void addSequentialAssigner(FlowContext flowContext){
        WorkFlowNode workFlowNode = flowContext.checkInstanceData(WorkFlowNode.class);
        WorkFlowInstance workFlowInstance = flowContext.checkInstanceData(WorkFlowInstance.class);
        CompleteTaskOption completeTaskOption = flowContext.checkInstanceData(CompleteTaskOption.class);
        List<WorkFlowAssigner> workFlowAssignerList = flowContext.checkData("workFlowAssignerList", List.class);
        Transaction transaction = flowContext.checkInstanceData(Transaction.class);

        List<WorkFlowTask> existWorkFlowTaskList = transaction.query(WorkFlowTask.class)
                .addQuery("instanceId", workFlowInstance.getId())
                .addQuery("nodeId", workFlowNode.getId())
                .addColumn("complete")
                .addColumn("assignerGroupIndex")
                .execute()
                .getList();

        int assignerGroupIndex = -1;
        if(null==existWorkFlowTaskList||existWorkFlowTaskList.isEmpty()){
            assignerGroupIndex = 0;
        }else{
            for(int i=0;i<workFlowAssignerList.size();i++){
                List<WorkFlowTask> currentWorkFlowTaskList = QueryInstanceList.newQuery(existWorkFlowTaskList)
                        .addQuery("assignerGroupIndex", i)
                        .execute()
                        .getList();
                int countOfComplete = 0;
                for(WorkFlowTask workFlowTask:currentWorkFlowTaskList){
                    if(workFlowTask.isComplete()){
                        countOfComplete++;
                    }
                }
                if(countOfComplete==currentWorkFlowTaskList.size()){
                    assignerGroupIndex++;
                }
            }
        }
        if(assignerGroupIndex<workFlowAssignerList.size()){
            completeTaskOption.shouldUpdateInstanceCurrentNodeId = false;
        }else{
            flowContext.brokenCurrentFlow("顺序审批已到达最后一个审批人");
        }

        addWorkFlowTaskByWorkFlowAssigner(assignerGroupIndex,flowContext);
    }

    private void replaceAssignerList(FlowContext flowContext){
        List<WorkFlowTask> workFlowTaskList = flowContext.getData("workFlowTaskList", List.class);

        for(WorkFlowTask workFlowTask:workFlowTaskList){
            flowContext.startFlow(new ReplaceAssignerCommonFlow())
                    .putCurrentCompositeFlowData("assigner", workFlowTask.getAssigner())
                    .execute();
            String assigner = flowContext.checkData("assigner", String.class);
            workFlowTask.setAssigner(assigner);
        }
    }

    private void addWorkFlowTaskByWorkFlowAssigner(int assignerGroupIndex, FlowContext flowContext){
        WorkFlowNode workFlowNode = flowContext.checkInstanceData(WorkFlowNode.class);
        WorkFlowInstance workFlowInstance = flowContext.checkInstanceData(WorkFlowInstance.class);
        List<WorkFlowTask> workFlowTaskList = flowContext.getData("workFlowTaskList", List.class);
        List<WorkFlowAssigner> workFlowAssignerList = flowContext.checkData("workFlowAssignerList", List.class);

        WorkFlowAssigner workFlowAssigner = workFlowAssignerList.get(assignerGroupIndex);
        switch (workFlowAssigner.assigneeType){
            case 0:{
                //指定人员
                for(String assigner:workFlowAssigner.assignerList){
                    WorkFlowTask workFlowTask = new WorkFlowTask();
                    workFlowTask.setInstanceId(workFlowInstance.getId());
                    workFlowTask.setNodeId(workFlowNode.getId());
                    workFlowTask.setTaskName(workFlowNode.getName());
                    workFlowTask.setAssigner(assigner);
                    workFlowTask.setAssignerGroupIndex(assignerGroupIndex);
                    workFlowTaskList.add(workFlowTask);
                }
            }break;
            case 1:{
                //发起人自选
                JSONArray manualWorkFlowAssignerArray = workFlowInstance.getMeta().getJSONArray("manualWorkFlowAssignerList");
                if(null==manualWorkFlowAssignerArray||manualWorkFlowAssignerArray.isEmpty()){
                    throw new IllegalArgumentException("未设置发起人自选审批人列表!节点名称:"+workFlowNode.getName()+",流程实例名称:"+workFlowInstance.getName());
                }
                List<ManualWorkFlowAssigner> manualWorkFlowAssignerList = manualWorkFlowAssignerArray.toJavaList(ManualWorkFlowAssigner.class);
                ManualWorkFlowAssigner manualWorkFlowAssigner = QueryInstanceList.newQuery(manualWorkFlowAssignerList)
                        .addQuery("nodeName", workFlowNode.getName())
                        .addQuery("assignerGroupIndex", assignerGroupIndex)
                        .execute()
                        .getOne();
                if(null==manualWorkFlowAssigner){
                    throw new IllegalArgumentException("发起人自选审批人不存在!节点名称:"+workFlowNode.getName()+",审批人序号:"+assignerGroupIndex);
                }
                for(String assigner:manualWorkFlowAssigner.assignerList){
                    WorkFlowTask workFlowTask = new WorkFlowTask();
                    workFlowTask.setInstanceId(workFlowInstance.getId());
                    workFlowTask.setNodeId(workFlowNode.getId());
                    workFlowTask.setTaskName(workFlowNode.getName());
                    workFlowTask.setAssigner(assigner);
                    workFlowTask.setAssignerGroupIndex(assignerGroupIndex);
                    workFlowTaskList.add(workFlowTask);
                }
            }break;
            default:{
                throw new IllegalArgumentException("不支持的审批人类型!当前值:"+workFlowAssigner.assigneeType+",允许值[0,1]");
            }
        }
    }
}